using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Script.Serialization;
using System.Collections.Specialized;
using System.Drawing;
using System.Web.UI.HtmlControls;
using System.Data;
using GridControl.Helpers;

namespace GridControl
{
    /// <summary>
    /// Control that represents an ExtJs Grid
    /// </summary>
    [ParseChildren(true)]
    [PersistChildren(true)]
    [Designer(typeof(YuiGridDesigner))]
    [ToolboxData("<{0}:YuiGrid runat=server></{0}:YuiGrid>")]
    [ToolboxBitmap(typeof(GridView))]
    public class YuiGrid : WebControl,INamingContainer
    {

        /// <summary>
        /// GridControlExtender to attach
        /// </summary>
        private GridControlExtender _extender;



        /// <summary>
        /// The columns of the grid
        /// </summary>
        private List<ColModel> _Columns;

        /// <summary>
        /// The DataSource for the grid
        /// </summary>
        private object _DataSource;

        /// <summary>
        /// Number of records 
        /// </summary>
        private int _TotalRecords;
        /// <summary>
        /// Helper -if true the grid will generate the
        /// columns automatically
        /// </summary>
        private bool _AutoGeneratColumns;

        /// <summary>
        /// Gets or sets a value indicating whether [auto generat columns].
        /// </summary>
        /// <value><c>true</c> if [auto generat columns]; otherwise, <c>false</c>.</value>
        [Browsable(true), Category("GridConfig"), Description("If the grid should auto-generate the columns")]
        public bool AutoGeneratColumns
        {
            get { return _AutoGeneratColumns; }
            set { _AutoGeneratColumns = value; }
        }

        /// <summary>
        /// Gets or sets the columns.
        /// </summary>
        /// <value>The columns.</value>
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public List<ColModel> Columns
        {
            get
            {
                EnsureChildControls();
                if (_Columns == null)
                {
                    _Columns = new List<ColModel>();
                }

                return _Columns;
            }

        }
        /// <summary>
        /// Gets or sets the fields.
        /// </summary>
        /// <value>The fields.</value>
        [Browsable(true), Category("GridConfig"), Description("Comma Separeted Fields that will be displayed on the Grid")]
        public string Fields
        {
            get
            {
                EnsureChildControls();
                return _extender.Fields;
            }
            set
            {
                EnsureChildControls();
                _extender.Fields = value;
            }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [enable row sorting].
        /// </summary>
        /// <value><c>true</c> if [enable row sorting]; otherwise, <c>false</c>.</value>
        [Browsable(true), Category("GridConfig"), Description("If drag and drop row sorting is enabled")]
        public bool EnableRowSorting
        {
            get
            {
                EnsureChildControls();
                return _extender.EnableRowSorting;
            }
            set
            {
                EnsureChildControls();
                _extender.EnableRowSorting = value;
            }
        }
        /// <summary>
        /// Gets or sets the size of the page.
        /// </summary>
        /// <value>The size of the page.</value>
        [Browsable(true), Category("GridConfig"), Description("Number of records in each page")]
        public int PageSize
        {
            get
            {
                EnsureChildControls();
                return _extender.PageSize;
            }
            set
            {
                EnsureChildControls();
                _extender.PageSize = value;
            }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [enable paging].
        /// </summary>
        /// <value><c>true</c> if [enable paging]; otherwise, <c>false</c>.</value>
        [Browsable(true), Category("GridConfig")]
        public bool EnablePaging
        {
            get
            {
                EnsureChildControls();
                return _extender.EnablePaging;
            }
            set
            {
                EnsureChildControls();
                _extender.EnablePaging = value;
            }
        }
        /// <summary>
        /// Gets or sets a value indicating whether [select multiple].
        /// </summary>
        /// <value><c>true</c> if [select multiple]; otherwise, <c>false</c>.</value>
        [Browsable(true), Category("GridConfig"), Description("Enable multi row selection")]
        public bool SelectMultiple
        {
            get
            {
                EnsureChildControls();
                return _extender.SelectMultiple;
            }
            set
            {
                EnsureChildControls();
                _extender.SelectMultiple = value;
            }
        }
        /// <summary>
        /// Gets or sets the web service method.
        /// </summary>
        /// <value>The web service method.</value>
        [Browsable(true), Category("GridConfig"), Description("Name of the webservice method to call")]
        public string WebServiceMethod
        {
            get
            {
                EnsureChildControls();
                return _extender.WebServiceMethod;
            }
            set
            {
                EnsureChildControls();
                _extender.WebServiceMethod = value;
            }
        }
        /// <summary>
        /// Gets or sets the web service path.
        /// </summary>
        /// <value>The web service path.</value>
        [Browsable(true), Category("GridConfig"), Description("Path of the webservice to call")]
        public string WebServicePath
        {
            get
            {
                EnsureChildControls();
                return _extender.WebServicePath;
            }
            set
            {
                EnsureChildControls();
                _extender.WebServicePath = value;
            }
        }
        /// <summary>
        /// Gets or sets the paging style.
        /// </summary>
        /// <value>The paging style.</value>
        [Browsable(true), Category("GridConfig"), Description("Page bar that will be draw")]
        public PagingStyle PagingStyle
        {
            get
            {
                EnsureChildControls();
                return _extender.PagingStyle;
            }
            set
            {
                EnsureChildControls();
                _extender.PagingStyle = value;
            }
        }

        /// <summary>
        /// Gets or sets the DataSource object. DataSet/DataTable/IEnumerator
        /// The data source cannot be parsed here ...its always an Ajax call
        /// </summary>
        [Browsable(true), Category("GridConfig"), Description("Gets or sets the DataSource object. DataSet/DataTable/IEnumerator.")]
        public object DataSource
        {
            set
            {
                this._DataSource = value;
            }
            get
            {
                return this._DataSource;
            }
        }

        /// <summary>
        /// The total number of records when
        /// the grid is DataBound- needed to page 
        /// </summary>
        public int TotalRecords
        {
            get
            {

                return _TotalRecords;
            }
            set
            {

                _TotalRecords = value;
            }
        }
        /// <summary>
        /// Default constructor that tells ASP.NET to render it as a DIV
        /// </summary>
        public YuiGrid()
            : base(HtmlTextWriterTag.Div)
        {
            this.Width = 300;
            this.Height = 300;

        }

        /// <summary>
        /// Prevent the Controls property from appearing in the editor (so
        /// that people will use the Panes collection instead)
        /// </summary>
        [EditorBrowsable(EditorBrowsableState.Never)]
        public override ControlCollection Controls
        {
            get
            {
                EnsureChildControls();
                return base.Controls;
            }
        }

        /// <summary>
        /// Create the child controls
        /// that will be generated for this control
        /// </summary>
        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            // Create the extender
            _extender = new GridControlExtender();

            _extender = new GridControlExtender();
            _extender.ID = this.ID + "_GridProperties";
            _extender.TargetControlID = ID;
            _extender.GridControlId = ID;
            //_extender.TargetProperties.Add(_extender);

            if (!this.DesignMode)
            {

                Controls.AddAt(0, _extender);
            }

            // If we already have items in the ViewState, create the control


            ClearChildViewState();
        }


        /// <summary>
        /// Renders the control to the specified HTML writer.
        /// </summary>
        /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"></see> object that receives the control content.</param>
        protected override void Render(HtmlTextWriter writer)
        {
            base.Render(writer);
     
           
        }

        /// <summary>
        /// Renders the initial html-tag of YuiGrid
        /// </summary>
        /// <param name="writer"></param>
        public override void RenderBeginTag(HtmlTextWriter writer)
        {
            if (!this.DesignMode)
            {
                string resource = Page.ClientScript.GetWebResourceUrl(GetType(), "GridControl.yui-ext.css");

                HtmlLink lnk = new HtmlLink();
                lnk.Href = resource;
                lnk.Attributes["rel"] = "stylesheet";
                lnk.Attributes["type"] = "text/css";

                Controls.Add(lnk);
                lnk.RenderControl(writer);

                resource = Page.ClientScript.GetWebResourceUrl(GetType(), "GridControl.NumberedPaging.css");


                lnk = new HtmlLink();
                lnk.Href = resource;
                lnk.Attributes["rel"] = "stylesheet";
                lnk.Attributes["type"] = "text/css";

                Controls.Add(lnk);
                lnk.RenderControl(writer);
            }
            base.RenderBeginTag(writer);
        }

        /// <summary>
        /// Raises the <see cref="E:System.Web.UI.Control.PreRender"></see> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"></see> object that contains the event data.</param>
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            if (!DesignMode)
            {
                if (_AutoGeneratColumns)
                {
                    AutoGenerate(true);
                }
                else
                {
                    if (this._DataSource != null)
                    {
                        AutoGenerate(false);
                    }
                }

                JavaScriptSerializer conv = new JavaScriptSerializer();
                string output = conv.Serialize(this.Columns);
                _extender.Columns = output;
            }
        }
        /// <summary>
        /// Generate columns and fields from data source
        /// </summary>
        /// <param name="generateColumns">true to generate columns and false to generate onlye fields</param>
        private void AutoGenerate(bool generateColumns)
        {
            if (generateColumns)
            {
                this.Columns.Clear();//ignore if the user set the columns
            }

            this.Fields = string.Empty;
            DataSet ds = this._DataSource as DataSet;
            DataTable dt = this._DataSource as DataTable;
            if (dt == null && ds != null)
            {
                dt = ds.Tables[0];
            }
            string strFields = string.Empty;
            int colWidth = (int)this.Width.Value / dt.Columns.Count -10;
            foreach (DataColumn dc in dt.Columns)
            {
                strFields += dc.ColumnName + ",";
                if (generateColumns)
                {
                    ColModel mdl = new ColModel();
                    mdl.header = dc.ColumnName;
                    mdl.sortable = true;
                    mdl.width = colWidth;
                    this.Columns.Add(mdl);
                }

            }
            strFields = strFields.Remove(strFields.Length - 1);
            this.Fields = strFields;
        }
        /// <summary>
        /// Runs only if it is an ajax Request 
        /// Builds the data to be loaded in the GridControlBehavior.js file
        /// </summary>
        public override void DataBind()
        {
            if (!string.IsNullOrEmpty(HttpContext.Current.Request["start"]))
            {
                if (_AutoGeneratColumns)
                {
                    AutoGenerate(true);
                }
                else
                {
                    if (this._DataSource != null)
                    {
                        AutoGenerate(false);
                    }
                }
                DataSet ds = this._DataSource as DataSet;
                DataTable dt = this._DataSource as DataTable;
                IEnumerable enu = this._DataSource as IEnumerable;

                string parsedValue = string.Empty;
                if (ds != null)
                    parsedValue = DataParserHelper.ParseData(ds, this.Fields);
                if (dt != null)
                    parsedValue = DataParserHelper.ParseData(dt, this.Fields);
                if (enu != null)
                    parsedValue = DataParserHelper.ParseData(enu, this.Fields);

                //EnsureChildControls();
                HttpResponse Response = HttpContext.Current.Response;
                Response.Clear();
                //Response.ContentType = "text";
                //JavaScriptSerializer ser = new JavaScriptSerializer();
                Response.Write("{\"records\":[" + parsedValue + "],\"totalCount\":\"" + this.TotalRecords + "\"}");
                Response.End();
            }

            //_extender.DataArray = parsedValue;
        }

    }
}